module StoryNavWidget exposing (WidgetData, Datum, Msg (..), navWidget)

import Time
import Html exposing (Html)
import LineChart
import LineChart.Junk as Junk
import LineChart.Area as Area
import LineChart.Axis as Axis
import LineChart.Axis.Title as Title
import LineChart.Axis.Range as Range
import LineChart.Axis.Ticks as Ticks
import LineChart.Axis.Tick as Tick
import LineChart.Axis.Line as AxisLine
import LineChart.Junk as Junk
import LineChart.Dots as Dots
import LineChart.Grid as Grid
import LineChart.Dots as Dots
import LineChart.Line as Line
import LineChart.Colors as Colors
import LineChart.Events as Events
import LineChart.Legends as Legends
import LineChart.Container as Container
import LineChart.Coordinate as Coordinate
import LineChart.Interpolation as Interpolation
import LineChart.Axis.Intersection as Intersection
import Color.Manipulate as Manipulate
import Svg
import Random.Pipeline
import Random

-- MODEL


-- type alias Model =
--     { widgetData : WidgetData
--     , hinted : Maybe Datum
--     }


type alias WidgetData =
    { one : List Datum
    , two : List Datum
    , three : List Datum
    }


type alias Datum =
    { xAxis : Float
    , yAxis : Float
    }

sampleWidgetData =
    { one = 
        [ { xAxis = 1.0, yAxis = 1.0 }
        , { xAxis = 2.0, yAxis = 1.0 }
        , { xAxis = 3.0, yAxis = 1.0 }
        ]
    , two = 
        [ { xAxis = 1.0, yAxis = 2.0 }
        , { xAxis = 2.0, yAxis = 2.0 }
        , { xAxis = 3.0, yAxis = 2.0 }
        , { xAxis = 4.0, yAxis = 2.0 }
        ]
    , three =
        [ { xAxis = 1.0, yAxis = 3.0 }
        , { xAxis = 2.0, yAxis = 3.0 }
        , { xAxis = 3.0, yAxis = 3.0 }
        , { xAxis = 4.0, yAxis = 3.0 }
        ]
    }


-- INIT


-- init : ( Model, Cmd Msg )
-- init =
--     ( { widgetData = WidgetData [] [] [] [] [] []
--         , hinted = Nothing
--         }
--     , sampleWidgetData --generateWidgetData
--     )
-- API


-- setWidgetData : WidgetData -> Model -> Model
-- setWidgetData widgetData model =
--     { model | widgetData = widgetData }


-- setHint : Maybe Datum -> Model -> Model
-- setHint hinted model =
--     { model | hinted = hinted }



-- UPDATE


type Msg
    = RecieveWidgetData WidgetData
    | Hint (Maybe Datum)


-- update : Msg -> Model -> ( Model, Cmd Msg )
-- update msg model =
--     case msg of
--         RecieveWidgetData numbers ->
--             model
--                 |> setWidgetData numbers
--                 |> addCmd Cmd.none

--         Hint point ->
--             model
--                 |> setHint point
--                 |> addCmd Cmd.none


-- addCmd : Cmd Msg -> Model -> ( Model, Cmd Msg )
-- addCmd cmd model =
--     ( model, Cmd.none )



-- VIEW


navWidget : WidgetData -> Maybe Datum -> Html Msg
navWidget data hinted =
    Html.div []
        [ LineChart.viewCustom (chartConfig hinted)
            [ LineChart.line (Manipulate.lighten 0.2 Colors.cyan) Dots.circle "One"   data.one
            , LineChart.line (Manipulate.lighten 0   Colors.cyan) Dots.circle "Two"    data.two
            , LineChart.line (Manipulate.lighten 0.2 Colors.blue) Dots.circle "Three"   data.three
            -- , LineChart.line (Manipulate.lighten 0   Colors.blue) Dots.circle "Greenland" model.widgetData.greenland
            -- , LineChart.line (Manipulate.lighten 0   Colors.pink) Dots.circle "Norway"    model.widgetData.norway
            -- , LineChart.line (Manipulate.darken  0.2 Colors.pink) Dots.circle "Finland"   model.widgetData.finland
            ]
        ]



-- CHART CONFIG


chartConfig : Maybe Datum -> LineChart.Config Datum Msg
chartConfig hinted =
    { y = yAxisConfig
    , x = xAxisConfig
    , container = containerConfig
    , interpolation = Interpolation.monotone
    , intersection = Intersection.default
    , legends = Legends.default
    , events = eventsConfig
    , junk = Junk.default
    , grid = Grid.default
    , area = Area.default
    , line = lineConfig hinted
    , dots = Dots.custom (Dots.disconnected 4 2)
    }



-- CHART CONFIG / AXES


yAxisConfig : Axis.Config Datum Msg
yAxisConfig =
    Axis.custom
        { title = Title.atDataMax -10 -10 "Items"
        , variable = Just << .yAxis
        , pixels = 450
        , range = Range.padded 20 20
        , axisLine = AxisLine.rangeFrame Colors.gray
        , ticks = Ticks.custom <| \dataRange axisRange ->
            [ tickRain ( dataRange.min, "bits" )
            , tickRain ( middle dataRange, "some" )
            , tickRain ( dataRange.max, "lots" )
            ]
        }


xAxisConfig : Axis.Config Datum Msg
xAxisConfig =
    Axis.custom
        { title = Title.default "Time"
        , variable = Just << .xAxis
        , pixels = 1270
        , range = Range.padded 20 20
        , axisLine = AxisLine.none
        , ticks = Ticks.float 10 --tickTime
        }



-- CHART CONFIG / AXES / TICKS


tickRain : ( Float, String ) -> Tick.Config msg
tickRain ( value, label ) =
    Tick.custom
        { position = value
        , color = Colors.gray
        , width = 1
        , length = 5
        , grid = True
        , direction = Tick.negative
        , label = Just (tickLabel label)
        }


-- tickTime : Tick.Time -> Tick.Config msg
-- tickTime time =
--     let label = Tick.format time in
--     Tick.custom
--         { position = time.timestamp
--         , color = Colors.gray
--         , width = 1
--         , length = 5
--         , grid = False
--         , direction = Tick.negative
--         , label = Just (tickLabel label)
--         }


tickLabel : String -> Svg.Svg msg
tickLabel =
    Junk.label Colors.black



-- CHART CONFIG / CONTIANER


containerConfig : Container.Config Msg
containerConfig =
    Container.custom
        { attributesHtml = []
        , attributesSvg = []
        , size = Container.relative
        , margin = Container.Margin 30 180 30 70
        , id = "line-chart-lines"
        }


-- CHART CONFIG / EVENTS



eventsConfig : Events.Config Datum Msg
eventsConfig =
    Events.custom
        [ Events.onMouseMove Hint Events.getNearest
        , Events.onMouseLeave (Hint Nothing)
        ]



-- CHART CONFIG / LINE


lineConfig : Maybe Datum -> Line.Config Datum
lineConfig maybeHovered =
    Line.custom (toLineStyle maybeHovered)


toLineStyle : Maybe Datum -> List Datum -> Line.Style
toLineStyle maybeHovered lineWidgetData =
    case maybeHovered of
        Nothing ->
            Line.style 1 identity

        Just hovered ->
            if List.any ((==) hovered) lineWidgetData then
                Line.style 2 identity
            else
                Line.style 1 (Manipulate.grayscale)



-- UTILS


round10 : Float -> Float
round10 float =
    toFloat (round (float * 10)) / 10


middle : Coordinate.Range -> Float
middle r =
    r.min + (r.max - r.min) / 2



-- GENERATE WidgetData


-- generateWidgetData : Cmd Msg
-- generateWidgetData =
--     let
--         genNumbers min max =
--             Random.list 10 (Random.float min max)

--         compile a b c d e f =
--             WidgetData (toWidgetData a) (toWidgetData b) (toWidgetData c) (toWidgetData d) (toWidgetData e) (toWidgetData f)
--     in
--     Random.Pipeline.with genNumbers
--     Random.Pipeline.generate compile
--         |> Random.Pipeline.with (genNumbers 50 90)
--         |> Random.Pipeline.with (genNumbers 20 60)
--         |> Random.Pipeline.with (genNumbers 30 60)
--         |> Random.Pipeline.with (genNumbers 40 90)
--         |> Random.Pipeline.with (genNumbers 80 100)
--         |> Random.Pipeline.with (genNumbers 70 90)
--         |> Random.Pipeline.send RecieveWidgetData


toWidgetData : List Float -> List Datum
toWidgetData numbers =
    let
        toDatum index rain =
            Datum (indexToTime index) rain
    in
    List.indexedMap toDatum numbers


indexToTime : Int -> Float
indexToTime index =
    toFloat index
    -- Time.hour * 24 * 365 * 30 + xInterval * toFloat index


-- xInterval : Time.Posix
-- xInterval =
--     Time.hour * 24 * 31



-- PROGRAM


-- main : Program Never Model Msg
-- main =
-- Html.program
--     { init = init
--     , update = update
--     , view = view
--     , subscriptions = always Sub.none
--     }
